题目链接:┏ (゜ω゜)=☞ 走起
题目大意
n 个城市 m 条路,每个城市都有救援小组,所有的边的边权已知。给定起点和终点,求从起点到终点的最短路径条数以及最短路径上的救援小组数目之和。如果有多条就输出点权(城市救援小组数目)最大的那个~
分析
用一遍 Dijkstra 算法,救援小组个数相当于点权,用 Dijkstra 求边权最小的最短路径的条数,以及这些最短路径中点权最大的值,d[i] 表示从出发点到 i 结点最短路径的路径长度,num[i] 表示从出发点到 i 结点最短路径的条数,team[i] 表示从出发点到 i 点救援队的数目之和,分最短路 < 和 = 两种情况更新数据。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include<bits/stdc++.h> using namespace std;
const int N = 510, INF = 0x3f3f3f3f; int g[N][N]; int d[N], team[N], w[N], num[N]; bool st[N];
int main() { int m, n, c1, c2; scanf("%d%d%d%d", &m, &n, &c1, &c2); for(int i = 0; i < m; i++) scanf("%d", &w[i]); memset(g, 0x3f, sizeof g); memset(d, 0x3f, sizeof d); int a, b, c; for(int i = 0; i < n; i++) { scanf("%d%d%d", &a, &b, &c); g[a][b] = g[b][a] = c; } d[c1] = 0; num[c1] = 1; team[c1] = w[c1]; for(int j = 0; j < n; j++) { int t = -1; for(int i = 0; i < n; i++) if(!st[i] && (t == -1 || d[t] > d[i])) t = i; st[t] = true; for(int i = 0; i < n; i++) { if(!st[i] && g[t][i] != INF) { if(d[t] + g[t][i] < d[i]) { d[i] = d[t] + g[t][i]; num[i] = num[t]; team[i] = team[t] + w[i]; } else if(d[t] + g[t][i] == d[i]) { num[i] += num[t]; team[i] = max(team[i], team[t] + w[i]); } } } } printf("%d %d", num[c2], team[c2]); return 0; }
|